import axios from 'axios';

import { dialog, ipcMain, IpcMainInvokeEvent } from 'electron';

import fs from 'fs';
import os from 'os';
import path from 'path';

// import fileIcon from 'extract-file-icon';

import IpcMessage from '../../preload/preload';
import MainCommonService from '../main-common-service';

export default class FileSystemIpcService {
  /**
   * Sets up all related ipc message listeners.
   */
  static setup(): void {
    // Two-way communications.
    this.download();
    // this.extractFileIcon();
    this.getSystemTempDir();
    this.loadAssetJsonFile();
    this.showOpenDirectoryDialogSync();
    this.showOpenFileDialog();
  }

  private static download(): void {
    ipcMain.handle(
      IpcMessage.download,
      async (
        event: IpcMainInvokeEvent,
        param: { url: string; targetDir?: string; targetFullName?: string },
      ): Promise<string> => {
        if (!param.targetDir && !param.targetFullName) {
          return '';
        }

        // Downloads file from url.
        const response = await axios({
          method: 'get',
          url: param.url,
          responseType: 'stream',
        });

        // Gets filename and saves it to system temp dir.
        // If file exists it will be overwritten.
        const filename = param.url.substring(param.url.lastIndexOf('/'), param.url.length);
        const fullPath =
          param.targetFullName != undefined
            ? param.targetFullName
            : path.join(param.targetDir!, filename);
        response.data.pipe(fs.createWriteStream(fullPath, { flags: 'w' }));

        return fullPath;
      },
    );
  }

  // private static extractFileIcon(): void {
  //   ipcMain.handle(IpcMessage.extractFileIcon, async (_: IpcMainInvokeEvent, fileFullName: string): Promise<string> => {
  // type IconSize = {
  //   [key: string]: 256 | 64 | 32 | 16
  // };

  // const sizes: IconSize = {
  //   a: 256,
  //   b: 64,
  //   c: 32,
  //   d: 16,
  // };

  // let iconData: Buffer | undefined | null = fileIcon(fileFullName);

  // if (iconData?.length == 0) {
  //   // It seems like we don't sure which size icon exists.
  //   // Thats why we need to check on each one size.
  //   for (const key in sizes) {
  //     iconData = fileIcon(fileFullName, sizes[key]);

  //     if (iconData?.length > 0) {
  //       break;
  //     }
  //   }
  // }

  // return iconData?.length > 0 ? Buffer.from(iconData).toString('base64') : '';
  //   });
  // }

  private static getSystemTempDir(): void {
    ipcMain.handle(IpcMessage.getSystemTempDir, async (): Promise<string> => os.tmpdir());
  }

  private static loadAssetJsonFile(): void {
    ipcMain.handle(
      IpcMessage.loadAssetJsonFile,
      async (_: IpcMainInvokeEvent, fileRelativePath: string): Promise<any | null> => {
        const rootPath = MainCommonService.getRootPath();
        const filePath = path.join(rootPath, 'assets', fileRelativePath);

        if (!fs.existsSync(filePath)) {
          return null;
        }

        const content = fs.readFileSync(filePath, { encoding: 'utf8' });

        return JSON.parse(content);
      },
    );
  }

  private static showOpenDirectoryDialogSync(): void {
    ipcMain.handle(
      IpcMessage.showOpenDirectoryDialogSync,
      async (): Promise<string[] | undefined> =>
        dialog.showOpenDialogSync({ properties: ['openDirectory', 'createDirectory'] }),
    );
  }

  private static showOpenFileDialog(): void {
    ipcMain.handle(IpcMessage.showOpenFileDialog, async (): Promise<string[] | undefined> => {
      const { canceled, filePaths } = await dialog.showOpenDialog({
        properties: ['openFile', 'createDirectory'],
      });

      if (canceled) {
        return;
      } else {
        return filePaths;
      }
    });
  }
}
